import io
import random
from django.contrib.auth import get_user_model
from django.http import HttpResponse
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from department.models import Department
from utils.crypto_tool import myDESCipher
from utils.tools import MyCaptchaImage, ThreadImgs
from .serializers import RegisterSerializer, LoginTokenObtainSerializer, RegisterCodeSerializer, UserSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from django.core.paginator import Paginator
User = get_user_model()


class GetLoginCodeGenericViewSet(GenericViewSet):
    """
    获取登录验证码的视图集
    
    该视图集用于生成并返回一个图形验证码，并将验证码存储在Redis缓存中，以便后续验证
    
    属性:
        myCaptchaImage (MyCaptchaImage): 用于生成图形验证码的工具类实例
    
    方法:
        retrieve: 根据传入的UUID生成验证码图片，并将验证码存储在Redis中，返回验证码图片
    """
    myCaptchaImage = MyCaptchaImage()

    def retrieve(self, request, uuid):
        """
        生成并返回图形验证码
        
        参数:
            request (HttpRequest): HTTP请求对象
            uuid (str): 唯一标识符，用于在Redis中存储验证码时作为键的一部分
        
        返回值:
            HttpResponse: 包含验证码图片的HTTP响应，内容类型为'image/png'
        """
        # 生成验证码图片和对应的验证码
        img, code = self.myCaptchaImage.generate_code()

        # 将图片转换为字节数据
        img_bytes = io.BytesIO()
        img.save(img_bytes, format='PNG')
        image_bytes = img_bytes.getvalue()  # 图片的字节数据

        # 将验证码存储在Redis中，键为'picturecode_{uuid}'，有效期为300秒
        cache = get_redis_connection(alias='verify_code_pic')
        code_template = f'picturecode_{uuid}'
        cache.set(f'{code_template}', code, 300)

        # 返回验证码图片
        return HttpResponse(image_bytes, content_type='image/png')


class GetRegisterCodeGenericViewSet(GenericViewSet):
    """
    获取注册验证码的视图集
    
    该视图集用于生成并发送手机验证码，并将验证码存储在Redis缓存中，以便后续验证
    
    属性:
        serializer_class (RegisterCodeSerializer): 用于验证请求数据的序列化器
    
    方法:
        create: 根据传入的手机号码生成验证码，并将验证码存储在Redis中，返回验证码发送结果
    """
    serializer_class = RegisterCodeSerializer
    queryset = User.objects.all()

    def create(self, request):
        """
        生成并发送手机验证码
        
        参数:
            request (HttpRequest): HTTP请求对象，包含用户提交的手机号码等信息
        
        返回值:
            Response: 包含验证码发送结果的HTTP响应，状态码和消息
        """
        # 使用序列化器验证请求数据
        serializer = self.get_serializer(data=request.data)
        if not serializer.is_valid():
            # 如果数据无效，直接返回序列化器的错误响应
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        # 获取已验证的手机号码
        mobile = request.data.get('mobile')
        if self.get_queryset().filter(phone_number=mobile).exists():
            return Response({
                "status": status.HTTP_409_CONFLICT,
                "msg": "该手机号已被注册，请换一个手机号进行注册",
            })
        # 生成4位随机数字验证码
        codes = ''.join(random.choices('123456789', k=4))
        # 假设验证码发送成功，将验证码存储在Redis中，键为'verify_code_phone-{mobile}'，有效期为300秒
        cache = get_redis_connection(alias='verify_code_phone')
        template = f'verify_code_phone-{mobile}'
        cache.set(f'{template}', codes, 300)
        # 返回验证码发送成功的响应
        return Response({
            'status': 200,
            'msg': '验证码已发送,请在5分钟之内完成验证！'
        })


class RegisterGenericViewSet(GenericViewSet):
    queryset = User.objects.all()
    serializer_class = RegisterSerializer

    def create(self, request):
        # 校验用户名是否存在
        user = self.get_queryset().filter(username=request.data.get("username")).first()
        if user:
            return Response({
                "status": status.HTTP_409_CONFLICT,
                "msg": "该用户已存在，请换一个用户名进行注册",
            })

        # 校验手机号是否存在
        mobile = request.data.get("phone_number")
        if self.get_queryset().filter(phone_number=mobile).exists():
            return Response({
                "status": status.HTTP_409_CONFLICT,
                "msg": "该手机号已被注册，请换一个手机号进行注册",
            })

        # 校验数据是否正确
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 校验验证码 如果不正确则返回报错信息
        cache = get_redis_connection(alias='verify_code_phone')
        template = f'verify_code_phone-{mobile}'
        redis_code = cache.get(template)
        if not redis_code:  # 如果redis_code为None
            redis_code = b'11111111111111'
        if redis_code.decode('utf-8') != request.data['code']:
            cache.delete(f'{template}')
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '验证码不正确，请重新输入'
            })

        # 如果正确，则删除验证码
        cache.delete(f'{template}')

        try:
            # 创建用户
            user_data = {
                'username': request.data.get('username'),
                'email': request.data.get('email'),
                'phone_number': mobile,
                'user_type': serializer.validated_data['user_type'],
                'is_active': False,  # 新注册用户默认为未激活状态
            }
            
            # 设置管理权限
            if serializer.validated_data['user_type'] == 'ADMIN':
                user_data['is_staff'] = True
                
            user = User(**user_data)
            user.set_password(serializer.validated_data['password'])
            user.save()
        except Exception as e:
            # 返回响应告知用户注册失败
            return Response({
                "status": status.HTTP_500_INTERNAL_SERVER_ERROR,
                "msg": f"注册失败，请稍后重试: {str(e)}",
            })

        # 如果一切正常，返回成功响应
        return Response({
            'status': status.HTTP_201_CREATED,
            'msg': '注册成功！您的账户需要管理员审核激活后才能登录，请联系管理员激活账户。'
        })


class LoginGenericViewSet(TokenObtainPairView):
    serializer_class = LoginTokenObtainSerializer

    def post(self, request, *args, **kwargs):

        # 校验用户信息
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 验证码校验
        cache = get_redis_connection(alias='verify_code_pic')
        code_template = f"picturecode_{request.data.get('uuid')}"
        #   取出redis里面的验证码
        redis_code = cache.get(code_template)
        if not redis_code:  # 如果redis_code为None
            redis_code = b'11111111111111'
        if redis_code.decode('utf-8').lower() != request.data.get('code'):
            cache.delete(f'{code_template}')
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '验证码不正确，请重新输入'
            })
        # 清除验证码
        cache.delete(f'{code_template}')

        try:
            user = serializer.validated_data['user']
        except KeyError:
            return Response({
                "status": status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在或密码错误"
            })

        response_data = {
            "status": status.HTTP_200_OK,
            "data": {
                "token": serializer.validated_data['access'],
                "username": user.username,
                "nickname": f"{user.first_name or ''}{user.last_name or ''}".strip() or user.username,
                "user_type": user.user_type,
                "user_id": myDESCipher.encrypt(str(user.id))
            }
        }
        return Response(response_data)


class UserViewSet(GenericViewSet):
    """
    用户信息管理视图集
    
    提供用户信息的查询、修改等功能
    """
    permission_classes = [IsAuthenticated]
    serializer_class = UserSerializer
    queryset = User.objects.all()
    
    @action(methods=['get'], detail=False)
    def profile(self, request):
        """获取当前登录用户的个人信息"""
        serializer = self.get_serializer(request.user)
        return Response({
            'status': status.HTTP_200_OK,
            'data': serializer.data
        })
    
    @action(methods=['put'], detail=False)
    def update_profile(self, request):
        """更新当前登录用户的个人信息"""
        serializer = self.get_serializer(request.user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({
                'status': status.HTTP_200_OK,
                'data': serializer.data,
                'msg': '个人信息更新成功'
            })
        return Response({
            'status': status.HTTP_400_BAD_REQUEST,
            'msg': serializer.errors
        })
    
    @action(methods=['get'], detail=False)
    def list_users(self, request):
        """管理员获取用户列表"""
        # 检查权限
        if not (request.user.user_type in ['ADMIN', 'MANAGER']):
            return Response({
                'status': status.HTTP_403_FORBIDDEN,
                'msg': '只有管理员和测试管理员可以查看用户列表'
            })
        
        # 获取查询参数
        page = int(request.GET.get('page', 1))
        page_size = int(request.GET.get('page_size', 10))
        search = request.GET.get('search', '')
        
        # 构建查询条件
        queryset = self.get_queryset()
        if search:
            queryset = queryset.filter(
                username__icontains=search
            ) | queryset.filter(
                email__icontains=search
            ) | queryset.filter(
                phone_number__icontains=search
            )
        
        # 分页处理
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page)
        
        # 序列化数据
        serializer = self.get_serializer(page_obj.object_list, many=True)
        
        return Response({
            'status': status.HTTP_200_OK,
            'data': {
                'users': serializer.data,
                'total': paginator.count,
                'page': page,
                'page_size': page_size,
                'total_pages': paginator.num_pages
            }
        })
    
    @action(methods=['put'], detail=True)
    def assign_department(self, request, pk=None):
        """管理员分配用户部门和员工编号"""
        # 检查权限
        if not (request.user.user_type in ['ADMIN', 'MANAGER']):
            return Response({
                'status': status.HTTP_403_FORBIDDEN,
                'msg': '只有管理员和测试管理员可以分配部门和员工编号'
            })
        
        try:
            user = self.get_object()
        except User.DoesNotExist:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                'msg': '用户不存在'
            })
        
        # 获取要更新的字段
        department_id = request.data.get('department_id')
        employee_id = request.data.get('employee_id', '')
        
        # 验证部门ID（如果提供）
        department = None
        if department_id:
            try:
                department = Department.objects.get(id=department_id, is_active=True)
            except Department.DoesNotExist:
                return Response({
                    'status': status.HTTP_400_BAD_REQUEST,
                    'msg': '指定的部门不存在或已被禁用'
                })
        
        # 检查员工编号是否已存在（如果提供了员工编号）
        if employee_id and User.objects.exclude(id=user.id).filter(employee_id=employee_id).exists():
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '该员工编号已被使用'
            })
        
        # 更新用户信息
        user.department = department
        user.employee_id = employee_id
        user.save()
        
        # 返回更新后的用户信息
        serializer = self.get_serializer(user)
        return Response({
            'status': status.HTTP_200_OK,
            'data': serializer.data,
            'msg': '用户部门和员工编号分配成功'
        })
    
    @action(methods=['put'], detail=True)
    def activate_user(self, request, pk=None):
        """管理员激活/禁用用户"""
        # 检查权限
        if not (request.user.user_type in ['ADMIN', 'MANAGER']):
            return Response({
                'status': status.HTTP_403_FORBIDDEN,
                'msg': '只有管理员和测试管理员可以激活用户'
            })
        
        try:
            user = self.get_object()
        except User.DoesNotExist:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                'msg': '用户不存在'
            })
        
        # 获取激活状态
        is_active = request.data.get('is_active', True)
        
        # 安全检查：不能禁用管理员账号
        if not is_active and user.user_type in ['ADMIN', 'MANAGER']:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '不能禁用管理员或测试管理员账号'
            })
        
        # 安全检查：不能禁用当前登录的用户
        if not is_active and user.id == request.user.id:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '不能禁用当前登录的账号'
            })
        
        # 安全检查：确保系统至少有一个激活的管理员
        if not is_active and user.user_type == 'ADMIN':
            active_admin_count = User.objects.filter(user_type='ADMIN', is_active=True).exclude(id=user.id).count()
            if active_admin_count == 0:
                return Response({
                    'status': status.HTTP_400_BAD_REQUEST,
                    'msg': '系统必须至少保留一个激活的管理员账号'
                })
        
        # 更新用户状态
        user.is_active = is_active
        user.save()
        
        action_text = '激活' if is_active else '禁用'
        
        # 返回更新后的用户信息
        serializer = self.get_serializer(user)
        return Response({
            'status': status.HTTP_200_OK,
            'data': serializer.data,
            'msg': f'用户{action_text}成功'
        })
    
    @action(methods=['post'], detail=False)
    def upload_avatar(self, request):
        """上传用户头像"""
        if 'avatar' not in request.FILES:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '请选择要上传的头像文件'
            })
        
        avatar_file = request.FILES['avatar']
        
        # 验证文件类型
        allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
        if avatar_file.content_type not in allowed_types:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '不支持的文件格式，请上传 JPEG、PNG、GIF 或 WebP 格式的图片'
            })
        
        # 验证文件大小（限制为2MB）
        if avatar_file.size > 2 * 1024 * 1024:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '文件大小不能超过2MB'
            })
        
        try:
            # 使用工具类上传图片
            thread_imgs = ThreadImgs()
            thread_imgs.circulate_add_file([avatar_file])
            
            if not thread_imgs.image_list:
                return Response({
                    'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
                    'msg': '图片上传失败，请稍后重试'
                })
            
            # 获取上传后的文件ID
            file_id = thread_imgs.image_list[0]
            
            # 只保存file_id，不包含域名和协议
            # 前端会通过/aps代理访问图片
            
            # 更新用户头像
            user = request.user
            user.avatar = file_id  # 只保存file_id
            user.save()
            
            return Response({
                'status': status.HTTP_200_OK,
                'data': {'avatar_url': file_id},
                'msg': '头像上传成功'
            })
            
        except Exception as e:
            return Response({
                'status': status.HTTP_500_INTERNAL_SERVER_ERROR,
                'msg': f'图片上传失败: {str(e)}'
            })
